﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;

namespace ModernUILogViewer.Elements.Helpers
{
    /// <summary>
    /// Attached Property for TextBoxBase
    /// Invoke a Command after some delay fired from TextChanged event 
    /// </summary>
    static class TextChangedCommandDelay
    {
        #region Fields

        const double DEFAULT_DELAY = 2.0;
        
        #endregion

        #region DependencyProperty

        public static readonly DependencyProperty CommandProperty =
           DependencyProperty.RegisterAttached("Command", typeof(ICommand),
           typeof(TextChangedCommandDelay), new FrameworkPropertyMetadata(OnCommandPropertyChanged));

        public static readonly DependencyProperty CommandParameterProperty =
           DependencyProperty.RegisterAttached("CommandParameter", typeof(object),
           typeof(TextChangedCommandDelay));

        public static readonly DependencyProperty DelayProperty =
           DependencyProperty.RegisterAttached("Delay", typeof(Double),
           typeof(TextChangedCommandDelay), new PropertyMetadata(DEFAULT_DELAY));

        #endregion

        #region Properties

        public static Double GetDelay(DependencyObject dp)
        {
            return (Double)dp.GetValue(DelayProperty);
        }

        public static void SetDelay(DependencyObject dp, Double value)
        {
            dp.SetValue(DelayProperty, value);
        }

        public static void SetCommand(DependencyObject dp, ICommand value)
        {
            dp.SetValue(CommandProperty, value);
        }

        public static ICommand GetCommand(DependencyObject dp)
        {
            return (ICommand)dp.GetValue(CommandProperty);
        }

        public static void SetCommandParameter(DependencyObject dp, object value)
        {
            dp.SetValue(CommandParameterProperty, value);
        }

        public static object GetCommandParameter(DependencyObject dp)
        {
            return (object)dp.GetValue(CommandParameterProperty);
        }

        #endregion

        #region Metadata

        private static void OnCommandPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            TextBoxBase txtboxbase = obj as TextBoxBase;

            Double delay = (Double)txtboxbase.GetValue(DelayProperty);
            ICommand command = (ICommand)e.NewValue;

            var input = Observable.FromEventPattern<TextChangedEventArgs>(txtboxbase, "TextChanged")
                .Select(evt => ((TextBox)evt.Sender).Text)
                .Throttle(TimeSpan.FromSeconds(delay))
                .DistinctUntilChanged()
                .ObserveOnDispatcher()
                .Subscribe((o) =>
                {
                    command.Execute(obj.GetValue(CommandParameterProperty));
                });
        }

        #endregion
    }
}
